package cn.lbd.arithmetic.leetcode.editor.cn;
//给定一个数组 nums，编写一个函数将所有 0 移动到数组的末尾，同时保持非零元素的相对顺序。
//
// 示例: 
//
// 输入: [0,1,0,3,12]
//输出: [1,3,12,0,0] 
//
// 说明: 
//
// 
// 必须在原数组上操作，不能拷贝额外的数组。 
// 尽量减少操作次数。 
// 
// Related Topics 数组 双指针 
// 👍 825 👎 0


import java.util.Arrays;

//leetcode submit region begin(Prohibit modification and deletion)
class Solution283 {
    //两次遍历：将非0元素左移的同时把指针j右移动，直到遍历完数组，j一定指向最后一个非0元素位置的下一位，从这一位开始再一次遍历剩余的数组，全部置为0
    /*public static void moveZeroes(int[] nums) {
        int j = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                nums[j++] = nums[i];
            }
        }
        for (int i = j; i < nums.length; i++) {
            nums[i] = 0;
        }
    }*/
    //一次遍历：利用快排思想，根据题意选取0作为分隔点，分隔点左边为非0元素，右边为0(如果一开始元素不是0也没关系，直接向下找0，找到了不是0的元素自然也在0左边还是符合题意)
    /*public static void moveZeroes(int[] nums) {
        int j = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0){
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j++] = tmp;
            }
        }
    }*/

    //优化一次遍历对开头非零元素无必要的交换过程，并将交换操作换成了赋值操作（因为这题的特殊性，交换的两个元素的其中一个必定是0）
    public static void moveZeroes(int[] nums) {
        int j = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0){
                if (i > j) {
                    nums[j] = nums[i];
                    nums[i] = 0;
                }
                //即使没有交换，但是当前这个元素在数组的位置也是确定的了，j还是要后移
                j++;
            }
        }
    }


    public static void main(String[] args) {
        int[] nums = new int[]{0,1,0,3,12};
        moveZeroes(nums);
        System.out.println(Arrays.toString(nums));
    }
}
//leetcode submit region end(Prohibit modification and deletion)
